﻿using System;
using System.Threading.Tasks;
using System.Threading;
using System.Runtime.InteropServices;

namespace ZeroBugBounce.Missive
{
	public interface IDispatchContext
	{
		void Execute();
		Handler Handler { get; set; }
		IHandlerContext HandlerContext { get; }
		Exception Exception { get; set; }
	}

	/// <summary>
	/// Dispatching is the taking of a message and a single handler and
	/// scheduling the handler running for that message
	/// </summary>
	/// <typeparam name="T"></typeparam>
	public class DispatchContext<T> : IDispatchContext
	{
		public DispatchContext(Messenger messenger, Handler<T> handler, 
			HandlerContext<T> handlerContext)
		{
			this.messenger = messenger;
			Handler = handler;
			HandlerContext = handlerContext;
		}

		internal Messenger messenger;
		public HandlerContext<T> HandlerContext { get; set; }
		public Handler<T> Handler { get; set; }

		public Exception Exception { get; set; }

		public void Execute()
		{
			Handler.Handle(HandlerContext);

			if (messenger.HasMessageHandledHandlers)
			{
				messenger.RaiseMessageHandled(
					HandlerContext.Topic,
					Handler.Topic,
					HandlerContext.Message,
					HandlerContext.CanReply,
					HandlerContext.CancellationToken.CanBeCanceled,
					HandlerContext.CancellationToken.IsCancellationRequested);
			}
		}

		Handler IDispatchContext.Handler
		{
			get
			{
				return this.Handler;
			}
			set
			{
				throw new NotImplementedException();
			}
		}

		IHandlerContext IDispatchContext.HandlerContext
		{
			get
			{
				return HandlerContext;
			}
		}
	}

}
